package com.regex;

import org.junit.Test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * App..
 *
 * @author Lizhong
 * @date 2019/7/1
 */
public class App {
    public static void main(String[] args) {

    }

    /**
     * 打印正则表达及匹配值
     * @param s
     * @param regexp
     */
    private void cout(String s, String regexp) {
        Pattern compile = Pattern.compile(regexp);
        Matcher matcher = compile.matcher(s);
        System.out.println("---------begin---------");
        while (matcher.find()) {
            String group = matcher.group();
            System.out.println(group);
        }
        System.out.println("---------end---------");
    }

    private void coutByGroup(String s, String regexp) {
        Pattern compile = Pattern.compile(regexp);
        Matcher matcher = compile.matcher(s);
        while (matcher.find()) {
            int i = matcher.groupCount();
            System.out.println(i + "=====find()======");
            for (int j = 0; j <= i; j++) {
                String group = matcher.group(j);
                System.out.println(group);
            }
        }
    }

    /**
     * js
     * var str = "Is is the cost of of gasoline going up up";
     * var patt1 = /( \b[a-z]+)\1/ig;
     * 匹配重复单词
     */
    @Test
    public void method01() {
        String s = "Is is the cost of of gasoline going up up";
        /**
         * (?i)忽略大小写
         * (?i)abc 表示abc都忽略大小写
         * a(?i)bc 表示bc忽略大小写
         * a((?i)b)c 表示只有b忽略大小写
         *
         *
         * ' \b'前一个是空格后一个位置是单词开始 '/b '相反，错误用 String s= 'a man';错误示例 regex='\\bman';
         * @see https://www.cnblogs.com/softidea/p/4925577.html
         *
         * \1获取子结果，表示重复的。
         */
        // String regexp = "(?i)([a-z]+)\\b \\1";
        String regexp = "(?i)([a-z]+)\\b \\1";
        boolean matches = s.matches(regexp);
        String[] split = s.split(regexp);
        for (String s1 : split) {
            System.out.println(s1);
        }
        System.out.println("---");
        cout(s, regexp);

    }

    /**
     * \\1 : 表示第一个括号重复的 "a8a8bb" "(\\d)(\\w)\\1" -> 8a8
     * \\2：表示第二个括号重复的 "a8a8bb" "(\\d)(\\w)\\2" -> 8bb
     */
    @Test
    public void method02() {
        String s = "a8a8bb";
        String regexp = "(\\d)(\\w)\\1";
        // String regexp = "(\\d)(\\w)\\2";
        cout(s, regexp);
    }

    /**
     * ? 贪心模式与+组合尽可能匹配
     * str="ppppmpp"
     * regexp="p"  p   p  p  p  p p
     * regexp="p+" pppp pp
     * regexp="p+?"  p   p  p  p  p p
     */
    @Test
    public void method03() {
        String s = "ppppmpp";
        String regexp = "p";
        // String regexp = "p+";
        // String regexp = "p+?";
        cout(s, regexp);
    }

    /**
     * 捕获型
     * $0、$1、$2 结合replaceAll使用
     * $0 http://www.qidian.com/BookReader/1017141,20361055.aspx
     * $1 http://www.qidian.com/BookReader/
     * $2 21017141
     * $3 20361055
     */
    @Test
    public void method04() {
        /**
         * 元数据
         * var reg=new RegExp("(http://www.qidian.com/BookReader/)(\\d+),(\\d+).aspx","gmi");
         * var url="http://www.qidian.com/BookReader/1017141,20361055.aspx";
         *
         * var rep=url.replace(reg,"$1ShowBook.aspx?bookId=$2&chapterId=$3");
         */
        String url = "http://www.qidian.com/BookReader/1017141,20361055.aspx";
        String regexp = "(http://www.qidian.com/BookReader/)(\\d+),(\\d+).aspx";
        // String s = url.replaceAll(regexp, "$1ShowBook.aspx?bookId=$2&chapterId=$3");
   /*     String s = url.replaceAll(regexp, "$0\n$1\n$2\n$3");
        System.out.println(s);*/

        Matcher matcher = Pattern.compile(regexp).matcher(url);
        while (matcher.find()) {
            int i = matcher.groupCount();
            System.out.println(i + "===========");
            for (int j = 0; j <= i; j++) {
                String group = matcher.group(j);
                System.out.println(group);
            }
        }
    }

    /**
     * 1: () 捕获组
     * 2: (?:) non capturing group
     * 3: (?=) positive lookahead    x(?=y) 含y，但不获取该表达式，可获取分组，匹配 x
     * 4: (?!) negative lookahead    x(?!y)不含y，但不获取该表达式，可获取分组，匹配x
     * 5: (?<=) positive lookbehind  (?<=y)x 前面有y匹配x
     * 6: (?<!) negative lookbehind  (?<!y)x 前面没有y匹配x
     * 7: (?=), (?!), (?<=), (?<!)的捕获
     */
    @Test
    public void method05() {
        // (?:)
        String s = "industry industries ";
        String regex = "industr(?:y|ies)"; // 等价于industry|industries
        cout(s, regex);
        coutByGroup(s, regex);
        // （?=）
        String s0 = "Windows95 Windows98 WindowsNT";
        String regexp0 = "Windows(?=95|98|NT|2000)";
        cout(s0, regexp0);
        // (?!)
        String s1 = "123ab55kl3";
        String regexp1 = "\\d+(?![a-z])";
        cout(s1, regexp1);
        // (?<=)
        String regexp2 = "(?<=[a-z])\\d";
        cout(s1, regexp2);

    }

    /**
     * (?:) ,不能捕获到 $或group
     */
    @Test
    public void method06() {
        String s =
                "2019.01.05";
        String regex = "(?:\\d{4}).(?:\\d{2}).(?:\\d{2})";
        String regex2 = "(\\d{4}).(\\d{2}).(\\d{2})";
        coutByGroup(s, regex);
        coutByGroup(s, regex2);
        /* Out
        0=====find()======
        2019.01.05
        3=====find()======
        2019.01.05
        2019
        01
        05
        */
    }

}
